#include <iostream>
#include <functional>
#include <math.h>
using namespace std;
// 基于对象的思想，通过bind和function
class Figure
{
public:
    using DisplayCallBack = function<void()>;
    using AreaCallBack = function<double()>;
    void setDisplayCallBack(DisplayCallBack &&cb)
    {
        _displayCallBack = std::move(cb);
    }
    void setAreaCallBack(AreaCallBack &&cb)
    {
        _areaCallBack = std::move(cb);
    }
    void handleDisplayCallBack() const
    {
        if (_displayCallBack)
        {
            _displayCallBack();
        }
    }
    double handleAreaCallBack() const
    {
        if (_areaCallBack)
        {
            return _areaCallBack();
        }
        else
        {
            return 0.0;
        }
    }
    DisplayCallBack _displayCallBack;
    AreaCallBack _areaCallBack;
};
class Rectangle
{
public:
    Rectangle(double len = 0, double width = 0)
        : _len(len), _width(width)
    {
        cout << "Rectangle(double = 0, double = 0)" << endl;
    }

    void display() const
    {
        cout << "Rectangle";
    }

    double area() const
    {
        return _len * _width;
    }

    ~Rectangle()
    {
        cout << "~Rectangle()" << endl;
    }

private:
    double _len;
    double _width;
};

// Circle c1 = 10;//int ===>Circle
class Circle
{
public:
    explicit Circle(double radius = 0)
        : _radius(radius)
    {
        cout << "Circle(double = 0)" << endl;
    }

    void print() const
    {
        cout << "Circle";
    }

    double printArea() const
    {
        return 3.14 * _radius * _radius;
    }

    ~Circle()
    {
        cout << "~Circle()" << endl;
    }

private:
    double _radius;
};

class Triangle
{
public:
    Triangle(double a = 0, double b = 0, double c = 0)
        : _a(a), _b(b), _c(c)
    {
        cout << "Triangle(double = 0, double = 0, double = 0)" << endl;
    }

    void show() const
    {
        cout << "Triangle";
    }

    double showArea() const
    {
        double tmp = (_a + _b + _c) / 2;
        return sqrt(tmp * (tmp - _a) * (tmp - _b) * (tmp - _c));
    }

    ~Triangle()
    {
        cout << "~Triangle()" << endl;
    }

private:
    double _a;
    double _b;
    double _c;
};
void func(const Figure &ref)
{
    ref.handleDisplayCallBack();
    cout << "面积为=" << ref.handleAreaCallBack() << endl;
}
void test()
{
    Figure fg;
    Rectangle rec(10, 20);
    Circle cir(10);
    Triangle tri(3, 4, 5);
    fg.setDisplayCallBack(bind(&Rectangle::display, &rec));
    fg.setAreaCallBack(bind(&Rectangle::area, &rec));
    func(fg);
    
    fg.setDisplayCallBack(bind(&Circle::print, &cir));
    fg.setAreaCallBack(bind(&Circle::printArea, &cir));
    func(fg);

    fg.setDisplayCallBack(bind(&Triangle::show, &tri));
    fg.setAreaCallBack(bind(&Triangle::showArea, &tri));
    func(fg);
}
int main()
{
    test();
    return 0;
}
